home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
networke
/
civ-0.000
/
civ-0
/
civ-0.3
/
src
/
rules.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-16
|
16KB
|
584 lines
#include "misc.h"
#include "rules.h"
#include "hash.h"
#include "list.h"
#include "units.h"
#include "debug.h"
#include "player.h"
#include "savefile.h"
#include <string.h>
struct ObjectList
{
char *name;
int type;
int unit;
int prodCost;
int maint;
};
typedef List<charp> Strings;
char *science_list[] = {
"Advanced Flight", "Flight", "Electricity", NULL,
"Bomber", "Carrier", NULL,
"Alphabet", NULL,
NULL,
"Astronomy", "Mysticism", "Mathematics", NULL,
"Copernicus Observatory", NULL,
"Atomic Theory", "Theory of Gravity", "Physics", NULL,
NULL,
"Automobile", "Combustion", "Steel", NULL,
"Armor", NULL,
"Banking", "Trade", "The Republic", NULL,
"Bank", NULL,
"Bridge Building", "Iron Working", "Construction", NULL,
NULL,
"Bronze Working", NULL,
"Phalanx", "Colossus", NULL,
"Ceremonial Burial", NULL,
"Temple", NULL,
"Chemistry", "University", "Medicine", NULL,
NULL,
"Chivalry", "Feudalism", "Horseback Riding", NULL,
"Knights", NULL,
"Code of Laws", "Alphabet", NULL,
"Courthouse", NULL,
"Combustion", "Refining", "Explosives", NULL,
"Cruiser", NULL,
"Communism", "Philosophy", "Industrialization", NULL,
"United Nations", NULL,
"Computers", "Mathematics", "Electricity", NULL,
"SETI Program", NULL,
"Conscription", "The Republic", "Explosives", NULL,
"Riflemen", NULL,
"Construction", "Masonry", "Currency", NULL,
"Aquaduct", "Colosseum", NULL,
"Currency", "Bronze Working", NULL,
"Marketplace", NULL,
"Democracy", "Philosophy", "Literacy", NULL,
NULL,
"Electricity", "Metallurgy", "Magnetism", NULL,
NULL,
"Electronics", "Engineering", "Electricity", NULL,
"Hydro Plant", "Hoover Dam", NULL,
"Engineering", "The Wheel", "Construction", NULL,
NULL,
"Explosives", "Gunpowder", "Chemistry", NULL,
NULL,
"Feudalism", "Masonry", "Monarchy", NULL,
NULL,
"Flight", "Combustion", "Physics", NULL,
"Fighter", NULL,
"Fusion Power", "Nuclear Power", "Superconductor", NULL,
"Fusion Plant", NULL,
"Genetic Engineering", "Medicine", "The Corporation", NULL,
"Cure for Cancer", NULL,
"Gunpowder", "Invention", "Iron Working", NULL,
"Musketeers", NULL,
"Horseback Riding", NULL,
"Cavalry", NULL,
"Industrialization", "Railroad", "Banking", NULL,
"Transport", "Factory", "Women's Suffrage", NULL,
"Invention", "Engineering", "Literacy", NULL,
NULL,
"Iron Working", "Bronze Working", NULL,
"Legion", NULL,
"Labor Union", "Mass Production", "Communism", NULL,
"Mech. Infantry", NULL,
"Literacy", "Writing", "Code of Laws", NULL,
"Great Library", NULL,
"Magnetism", "Navigation", "Physics", NULL,
"Frigate", NULL,
"Map Making", "Alphabet", NULL,
"Trireme", "Light House", NULL,
"Masonry", NULL,
"Palace", "City Walls", "Pyramids", "Great Wall", NULL,
"Mass Production", "Automobile", "The Corporation", NULL,
"Submarine", "Mass Transit", NULL,
"Mathematics", "Alphabet", "Masonry", NULL,
"Catapult", NULL,
"Medicine", "Philosophy", "Trade", NULL,
"Shakespeare's Theatre", NULL,
"Metallurgy", "Gunpowder", "University", NULL,
"Cannon", NULL,
"Monarchy", "Ceremonial Burial", "Code of Laws", NULL,
NULL,
"Mysticism", "Ceremonial Burial", NULL,
"Oracle", NULL,
"Navigation", "Map Making", "Astronomy", NULL,
"Sail", "Magellan's Expedition", NULL,
"Nuclear Fission", "Mass Production", "Atomic Theory", NULL,
"Manhattan Project", NULL,
"Nuclear Power", "Nuclear Fission", "Electronics", NULL,
"Nuclear Plant", NULL,
"Philosophy", "Mysticism", "Literacy", NULL,
NULL,
"Physics", "Mathematics", "Navigation", NULL,
NULL,
"Plastics", "Refining", NULL,
NULL,
"Pottery", NULL,
"Granary", "Hanging Gardens", NULL,
"Railroad", "Bridge Building", "Steam Engine", NULL,
"Darwin's Voyage", NULL,
"Recycling", "Mass Production", "Democracy", NULL,
"Recycling Ctr", NULL,
"Refining", "Chemistry", "The Corporation", NULL,
"Power Plant", NULL,
"Religion", "Philosophy", "Writing", NULL,
"Cathedral", "Michelangelo's Chapel", "J.S. Bach's Cathedral", NULL,
"Robotics", "Plastics", "Computers", NULL,
"Artillery", "Mfg. Plant", NULL,
"Rocketry", "Advanced Flight", "Electronics", NULL,
"Nuclear", NULL,
"Steam Engine", "Physics", "Invention", NULL,
"Ironclad", NULL,
"Steel", "Metallurgy", "Industrialization", NULL,
"Battleship", NULL,
"Superconductor", "Plastics", "Mass Production", NULL,
"SDI Defense", NULL,
"Survival", NULL,
"Settlers", "Militia", NULL,
"The Corporation", "Banking", "Industrialization", NULL,
NULL,
"The Republic", "Code of Laws", "Literacy", NULL,
NULL,
"The Wheel", NULL,
"Chariot", NULL,
"Theory of Gravity", "Astronomy", "University", NULL,
"Isaac Newton's College", NULL,
"Trade", "Currency", "Code of Laws", NULL,
"Caravan", NULL,
"University", "Mathematics", "Philosophy", NULL,
"University", NULL,
"Writing", "Alphabet", NULL,
"Diplomat", "Library", NULL,
NULL
};
ObjectList object_list[] = {
{ "Armor", ARMOR, 1, 80, 0 },
{ "Artillery", ARTILLERY, 1, 60, 0 },
{ "Battleship", BATTLESHIP, 1, 160, 0 },
{ "Bomber", BOMBER, 1, 120, 0 },
{ "Cannon", CANNON, 1, 40, 0 },
{ "Caravan", CARAVAN, 1, 50, 0 },
{ "Carrier", CARRIER, 1,160, 0 },
{ "Catapult", CATAPULT, 1, 40, 0 },
{ "Cavalry", CAVALRY, 1, 20, 0 },
{ "Chariot", CHARIOT, 1, 40, 0 },
{ "Cruiser", CRUISER, 1, 80, 0 },
{ "Diplomat", DIPLOMAT, 1, 30, 0 },
{ "Fighter", FIGHTER, 1, 60, 0 },
{ "Frigate", FRIGATE, 1, 40, 0 },
{ "Ironclad", IRONCLAD, 1, 60, 0 },
{ "Knights", KNIGHTS, 1, 40, 0 },
{ "Legion", LEGION, 1, 20, 0 },
{ "Mech. Infantry", MECH_INF, 1, 50, 0 },
{ "Militia", MILITIA, 1, 10, 0 },
{ "Musketeers", MUSKETEERS, 1, 30, 0 },
{ "Nuclear", NUCLEAR, 1, 160, 0 },
{ "Phalanx", PHALANX, 1, 20, 0 },
{ "Riflemen", RIFLEMEN, 1, 30, 0 },
{ "Sail", SAIL, 1, 40, 0 },
{ "Settlers", SETTLER, 1, 40, 0 },
{ "Submarine", SUBMARINE, 1, 50, 0 },
{ "Transport", TRANSPORT, 1, 50, 0 },
{ "Trireme", TRIREME, 1, 40, 0 },
{ "Copernicus Observatory", COPERNICUS, 2, 300, 0 },
{ "Bank", BANK, 0, 120, 3 },
{ "Colossus", COLOSSUS, 2, 200, 0 },
{ "Temple", TEMPLE, 0, 40, 1 },
{ "Courthouse", COURTHOUSE, 0, 80, 1 },
{ "United Nations", UNITEDNATIONS, 2, 600, 0 },
{ "SETI Program", SETIPROGRAM, 2, 600, 0 },
{ "Aquaduct", AQUADUCT, 0, 120, 2 },
{ "Colosseum", COLOSSEUM, 0, 100, 3 },
{ "Marketplace", MARKETPLACE, 0, 80, 1 },
{ "Hydro Plant", HYDROPLANT, 0, 240, 4 },
{ "Hoover Dam", HOOVERDAM, 2, 600, 0 },
{ "Cure for Cancer", CUREFORCANCER, 2, 600, 0 },
{ "Factory", FACTORY, 0, 200, 4 },
{ "Women's Suffrage", WOMENSSUFFRAGE, 2, 600, 0 },
{ "Great Library", GREATLIBRARY, 2, 300, 0 },
{ "Light House", LIGHTHOUSE, 2, 200, 0 },
{ "Palace", PALACE, 0, 100, 4 },
{ "City Walls", CITYWALLS, 0, 120, 2 },
{ "Pyramids", PYRAMIDS, 2, 300, 0 },
{ "Great Wall", GREATWALL, 2, 300, 0 },
{ "Mass Transit", MASSTRANSIT, 0, 160, 4 },
{ "Shakespeare's Theatre", SHAKESPEARE, 2, 400, 0 },
{ "Oracle", ORACLE, 2, 300, 0 },
{ "Magellan's Expedition", MAGELLAN, 2, 400, 0 },
{ "Manhattan Project", MANHATTAN, 2, 600, 0 },
{ "Granary", GRANARY, 0, 60, 1 },
{ "Hanging Gardens", HANGINGGARDENS, 2, 300, 0 },
{ "Darwin's Voyage", DARWIN, 2, 300, 0 },
{ "Recycling Ctr", RECYCLINGCTR, 0, 200, 2 },
{ "Power Plant", POWERPLANT, 0, 160, 4 },
{ "Fusion Plant", FUSIONPLANT, 0, 160, 4 },
{ "Nuclear Plant", NUCLEARPLANT, 0, 200, 4 },
{ "Cathedral", CATHEDRAL, 0, 160, 3 },
{ "Michelangelo's Chapel", MICHELANGELO, 2, 300, 0 },
{ "J.S. Bach's Cathedral", JSBACH, 2, 400, 0 },
{ "Mfg. Plant", MFGPLANT, 0, 320, 6 },
{ "SDI Defense", SDIDEFENSE, 0, 200, 4 },
{ "Isaac Newton's College", ISAACNEWTON, 2, 400, 0 },
{ "University", UNIVERSITY, 0, 160, 3 },
{ "Library", LIBRARY, 0, 80, 1 },
{ NULL, 0, 0, 0, 0 }
};
char *object_need_list[] = {
"University", "Library", NULL,
"Bank", "Marketplace", NULL,
"Power Plant", "Factory", NULL,
"Mfg. Plant", "Factory", NULL,
"Hydro Plant", "Factory", NULL,
"Nuclear Plant", "Factory", NULL,
"Fusion Plant", "Factory", NULL,
NULL
};
char *obselete_list[] = {
"Phalanx", "Militia",
"Cannon", "Catapult",
"Armor", "Cannon",
"Knights", "Chariot",
"Sail", "Trireme",
"Frigate", "Sail",
"Transport", "Frigate",
"Cruiser", "Ironclad",
"Musketeers", "Phalanx",
"Riflemen", "Musketeers",
NULL };
char *wonder_obsolete_list[] = {
"Pyramids", "Communism",
"Hanging Gardens", "Invention",
"Colossus", "Electricity",
"Light House", "Magnetism",
"Great Library", "University",
"Oracle", "Religion",
"Great Wall", "Gunpowder",
"Michelangelo's Chapel", "Communism",
"Copernicus Observatory", "Automobile",
"Shakespeare's Theatre", "Electronics",
"Isaac Newton's College", "Nuclear Fission",
NULL
};
HashTable<Science, StrKey> sciences(201);
HashTable<BuildObject, StrKey> buildObjects(201);
// hashes on science, each object is a list of science names which
// need the key science
HashTable<Strings, StrKey> needTable(201);
List<charp> scienceNames;
char **NewScience(char **ptr)
{
Science *sc = new Science;
sc->name = *ptr++;
sc->discovered = 0;
sc->wonderObsolete = NULL;
while (*ptr != NULL) {
char *name = *ptr++;
sc->need.Insert(name);
Strings *strings = needTable.Find(StrKey(name));
if (strings == NULL) {
strings = new Strings;
needTable.Insert(strings, StrKey(name));
}
strings->Insert(sc->name); // sc->name depends on name
}
++ptr; // get past NULL
while (*ptr != NULL)
sc->canBuild.Insert(*ptr++);
++ptr; // get past NULL
sciences.Insert(sc, StrKey(sc->name));
scienceNames.Insert(sc->name);
return ptr;
}
ObjectList *NewObject(ObjectList *objList)
{
BuildObject *obj = new BuildObject;
obj->name = objList->name;
obj->type = objList->type;
obj->unit = objList->unit == 1;
obj->wonder = objList->unit == 2;
obj->prodCost = objList->prodCost;
obj->maint = objList->maint;
obj->built = 0;
obj->isObsolete = 0;
obj->obsolete = NULL;
obj->line = new char[60];
if (obj->unit) {
// must match with selection handling in player.cc
sprintf(obj->line, "%s %d/%d/%d %d",obj->name,
UnitAttack(obj->type),
UnitDefense(obj->type),
UnitMoves(obj->type),
obj->prodCost
);
} else
// must match with selection handling in player.cc
sprintf(obj->line, "%s %d",obj->name,
obj->prodCost
);
buildObjects.Insert(obj, StrKey(obj->name));
++objList;
return objList;
}
void CheckRules()
{
// for each science, check that the thing it needs is in the science
// table
// also check the things it can build are in the objects table
for (Lister<charp> lister = scienceNames; lister; lister.Next()) {
char *name = lister.Elem();
Science *sc = sciences.Find(StrKey(name));
Lister<charp> l = sc->need;
while (l) {
if (sciences.Find(StrKey(l.Elem())) == NULL)
Debug('r', "Science %s depends on non existant %s\n", name, l.Elem());
l.Next();
}
l = sc->canBuild;
while (l) {
if (buildObjects.Find(StrKey(l.Elem())) == NULL)
Debug('r', "Science %s can't build non existant %s\n", name, l.Elem());
l.Next();
}
}
}
void InitializeRules()
{
char **ptr = science_list;
while (*ptr != NULL)
ptr = NewScience(ptr);
ObjectList *obj = object_list;
while (obj->name != NULL)
obj = NewObject(obj);
ptr = object_need_list;
while (*ptr != NULL) {
BuildObject *obj = buildObjects.Find(StrKey(*ptr));
if (obj == NULL)
Debug('r', "Can't find object %s in InitializeRules\n", *ptr);
while (*++ptr != NULL)
obj->neededObj.Insert(*ptr);
++ptr;
}
ptr = obselete_list;
while (*ptr != NULL) {
BuildObject *obj = buildObjects.Find(StrKey(*ptr++));
if (obj == NULL)
Debug('r', "Can't find %s in Obselete\n", *(ptr-1));
else
obj->obsolete = *ptr;
++ptr;
}
ptr = wonder_obsolete_list;
while (*ptr != NULL) {
BuildObject *obj = buildObjects.Find(StrKey(*ptr++));
if (obj == NULL)
Debug('r', "Can't find %s in obsolete\n", *(ptr-1));
Science *sc = sciences.Find(StrKey(*ptr++));
if (sc == NULL)
Debug('r', "Can't find %s in obsolete\n", *(ptr-1));
if (sc != NULL)
sc->wonderObsolete = obj->name;
}
CheckRules();
}
void CanDiscover(int player, char *science, List<charp> &canDiscover)
{
Science *ptr = sciences.Find(StrKey(science));
int can = 1;
for (Lister<charp> needl = ptr->need; needl && can; needl.Next()) {
Science *ptr1 = sciences.Find(needl.Elem());
if (ptr1 != NULL)
can = ptr1->discovered & (1<<player);
else
can = players[player]->HasWonder(needl.Elem());
}
if (can)
canDiscover.Insert(ptr->name);
}
void Discover(int player, char *science, List<charp> &discovered,
List<charp> &canDiscover, List<charp> &canBuild,
List<charp> &canGovern)
{
Debug('r', "Discovering %s for %d\n", science, player);
Science *ptr = sciences.Find(StrKey(science));
science = ptr->name;
if (strcmp(science, "Mysticism") == 0)
players[player]->templeEffect = 2;
if (strcmp(science, "Survival") == 0) canGovern.Insert("Despotism");
if (strcmp(science, "Monarchy") == 0)
canGovern.Insert("Monarchy");
if (strcmp(science, "The Republic") == 0)
canGovern.Insert("The Republic");
if (strcmp(science, "Democracy") == 0)
canGovern.Insert("Democracy");
discovered.Insert(science);
Lister<charp> lister;
for (lister = canDiscover; lister; lister.Next())
if (strcmp(lister.Elem(), science) == 0) {
lister.Delete();
break;
}
ptr->discovered |= 1 << player;
if (ptr->wonderObsolete != NULL) {
BuildObject *wonder = buildObjects.Find(StrKey(ptr->wonderObsolete));
if (!wonder->isObsolete) {
wonder->isObsolete = 1;
AddMessage(players[playerId]->messages, "%s makes %s obsolete",
science, ptr->wonderObsolete);
}
}
Strings *strings = needTable.Find(StrKey(science));
if (strings != NULL) {
for (Lister<charp> stringl = *strings; stringl; stringl.Next()) {
CanDiscover(player, stringl.Elem(), canDiscover);
}
}
for (lister = ptr->canBuild; lister; lister.Next()) {
char *name = lister.Elem();
canBuild.Insert(name);
BuildObject *obj = buildObjects.Find(StrKey(name));
if (obj->obsolete != NULL) {
for (Lister<charp> l = canBuild; l; l.Next())
if (strcmp(l.Elem(), obj->obsolete) == 0) {
l.Delete();
break;
}
}
}
}
void InitialScience(int player, List<charp> &discovered,
List<charp> &canDiscover, List<charp> &canBuild,
List<charp> &canGovern)
{
Lister<charp> l = scienceNames;
// look for all sciences with an empty need list put into canDiscover
// and discover survival
while (l) {
Science *sc = sciences.Find(StrKey(l.Elem()));
if (!sc->need)
canDiscover.Insert(sc->name);
l.Next();
}
Discover(player, "Survival", discovered, canDiscover, canBuild, canGovern);
}
// MarkM added variable discovery costs for sciences:
// basically this was simply the recursive number of required sciences x15
// however that was too fast so now trying 15 x (1+number already have)
int DiscoverCost(int player, Science *ptr)
{
// if (ptr == NULL) return 0;
// int cost = 15;
// for (Lister<charp> needl = ptr->need; needl; needl.Next()) {
// Science *ptr1 = sciences.Find(needl.Elem());
// if (ptr1 != NULL) cost += DiscoverCost(ptr1);
// }
// return cost;
return players[player]->discovered.Count() * 15;
}
int Discovered(int player, char *science)
{
Science *sc = sciences.Find(StrKey(science));
if (sc == NULL) return 0;
return sc->discovered & (1<<player);
}
int WonderObsolete(BuildObject *wonder, int player)
{
return wonder->isObsolete;
}